<script setup lang="ts">
import { ref } from "vue";
const CHUNK_SIZE = 10 * 1024 * 1024; // 10MB
const API_BASE = "http://localhost:3000";
const uploading = ref<Boolean>(false);
const hash = ref<String>("");
const file = ref<File | null>(null);
const statusText = ref<String>("");
import axios from "axios";
import SparkMD5 from "spark-md5";
const handleFileChange = (uploadFile: { raw: File }) => {
  file.value = uploadFile.raw;
};
// 生成hash文件
const calculateHash = async (file: File) => {
  return new Promise<string>((resolve, reject) => {
    const spark = new SparkMD5.ArrayBuffer();
    const reader = new FileReader();
    const chunkSize = CHUNK_SIZE;
    let currentChunk = 0;
    const chunks = Math.ceil(file.size / chunkSize);
    const loadNext = () => {
      const start = currentChunk * chunkSize;
      const end =
        start + chunkSize >= file.size ? file.size : start + chunkSize;
      reader.readAsArrayBuffer(file.slice(start, end));
    };
    reader.onload = (e: any) => {
      spark.append(e.target.result);
      currentChunk++;
      if (currentChunk < chunks) {
        loadNext();
      } else {
        resolve(spark.end());
      }
    };
    reader.onerror = reject;
    loadNext();
  });
};
const handleUpload = async () => {
  if (!file.value) return;
  try {
    statusText.value = "正在计算文件MD5...";
    hash.value = await calculateHash(file.value);
    // 创建分片
    const chunks = Math.ceil(file.value.size / CHUNK_SIZE);
    const requests = [];
    for (let index = 0; index < chunks; index++) {
      const start = index * CHUNK_SIZE;
      const end =
        start + CHUNK_SIZE >= file.value.size
          ? file.value.size
          : start + CHUNK_SIZE;
      const chunk = file.value.slice(start, end);
      const formData = new FormData();
      formData.append("hash", hash.value.toString());
      formData.append("index", index.toString());
      formData.append("chunk", chunk, `${hash.value}-${index}`);
      requests.push(axios.post(`${API_BASE}/upload`, formData));
    }
    // 上传所有分片
    await Promise.all(requests);
    // 合并分片
    await axios.post(`${API_BASE}/merge`, {
      hash: hash.value,
      filename: file.value.name,
      size: file.value.size,
    });
    statusText.value = "上传成功！";
  } catch (err: any) {
    statusText.value = "上传失败：" + err.message;
  }
};
</script>

<template>
  <div class="upload-container">
    <el-upload
      action=""
      :auto-upload="false"
      :on-change="handleFileChange"
      :show-file-list="false"
    >
      <template #trigger>
        <el-button type="primary">选择文件</el-button>
      </template>
      <el-button
        type="success"
        @click="handleUpload"
        :disabled="!file || uploading"
      >
        {{ uploading ? "上传中..." : "开始上传" }}
      </el-button>
    </el-upload>
    <div class="status">
      {{ statusText }}
    </div>
  </div>
</template>

<style scoped>
.upload-container {
  max-width: 800px;
  margin: 50px auto;
  padding: 20px;
}

.el-progress {
  margin: 20px 0;
}

.status {
  margin-top: 10px;
  color: #666;
  font-size: 14px;
}
</style>
